#include "xsRendPCH.hpp"

#include "rend_SpriteImpl.h"

namespace xs
{

//=================================================================================================
// SpriteImpl::SpriteImpl
//=========

SpriteImpl::SpriteImpl(Renderer *_xse):
xse(_xse), m_frame_delay(0)
{
	set_color(ARGB(255,255,255,255));
	set_source_rect(Rect(0,0, 128, 128));
	set_hot_spot(pos2(0,0));
	set_blend(xs::Blends::ALPHA);
}

//=================================================================================================
// SpriteImpl::~SpriteImpl
//=========

SpriteImpl::~SpriteImpl()
{
}

//=================================================================================================
// SpriteImpl::draw
//=========

void SpriteImpl::draw(const float &x, const float &y, f32 w, f32 h, const float &angle)
{
	draw_mirrored(false, false, x, y, w, h, angle);
}

//=================================================================================================
// SpriteImpl::draw_mirrored
//=========

void SpriteImpl::draw_mirrored(bool mirror_v, bool mirror_h, const float &x, const float &y, f32 w, f32 h, const float &angle)
{
	if(w==0) w = source_rect.w;
	if(h==0) h = source_rect.h;

	Vertex *v = quad.v;

	const float Umin = (source_rect.x-mirror_v)/tex_width;
	const float Umax = (source_rect.x+source_rect.w-mirror_v)/tex_width;
	const float Vmin = (source_rect.y-mirror_h)/tex_height;
	const float Vmax = (source_rect.y+source_rect.h-mirror_h)/tex_height;

	v[0].x = x; v[0].y = y;
	v[0].u = Umin; v[0].v = Vmin;

	v[1].x = x+w; v[1].y = y;
	v[1].u = Umax; v[1].v = Vmin;

	v[2].x = x+w; v[2].y = y+h;
	v[2].u = Umax; v[2].v = Vmax;

	v[3].x = x; v[3].y = y+h;
	v[3].u = Umin; v[3].v = Vmax;

	for(int i=0; i<4; i++)
	{
		quad.v[i].x -= hot_spot[0];
		quad.v[i].y -= hot_spot[1];
	}

	if(angle!=0.0f)
	{
		for(int i=0; i<4; i++)
		{
			pos2 p(quad.v[i].x-x, quad.v[i].y-y);

			p = cml::rotate_vector_2D(p, angle*xs::DEGTORAD);

			p += pos2(x, y);

			quad.v[i].x = p[0];
			quad.v[i].y = p[1];
		}
	}

	if(mirror_v)
	{
		std::swap(quad.v[0].u, quad.v[1].u);
		std::swap(quad.v[2].u, quad.v[3].u);
	}

	if(mirror_h)
	{
		std::swap(quad.v[0].v, quad.v[2].v);
		std::swap(quad.v[1].v, quad.v[3].v);
	}

	xse->render_quad(quad);
}

//=================================================================================================
// SpriteImpl::animate
//=========

bool SpriteImpl::animate(const unsigned int &elapsed_ms)
{
	if(frames.empty() || m_frame_delay==0) return false;

	const unsigned int curr_frame = elapsed_ms/m_frame_delay;

	source_rect = frames[curr_frame % frames.size()];

	return curr_frame < frames.size();
}

//=================================================================================================
// Getters/Setters
//=================================================================================================

unsigned int SpriteImpl::get_frame_delay()
{
	return m_frame_delay;
}
//=================================================================================================
void SpriteImpl::set_frame_delay(const unsigned int &frame_delay)
{
	m_frame_delay = frame_delay;
}
//=================================================================================================
void SpriteImpl::set_blend(const Blend &_blend)
{
	quad.blend = _blend;
}
//=================================================================================================
Blend SpriteImpl::get_blend()
{
	return quad.blend;
}
//=================================================================================================
void SpriteImpl::set_color(const Color &color)
{
	for(int i=0; i<4; i++)
		quad.v[i].color = color;
}
//=================================================================================================
Color SpriteImpl::get_color()
{
	return quad.v[0].color;
}
//=================================================================================================
void SpriteImpl::set_hot_spot(const pos2 &_hot_spot)
{
	hot_spot = _hot_spot;
}
//=================================================================================================
pos2 SpriteImpl::get_hot_spot()
{
	return hot_spot;
}
//=================================================================================================
void SpriteImpl::set_source_rect(const Rect &rect)
{
	source_rect = rect;
}
//=================================================================================================
Rect SpriteImpl::get_source_rect()
{
	return source_rect;
}
//=================================================================================================
void SpriteImpl::set_texture(const xs::Texture &texture)
{
	quad.texture = texture;
	int w=0, h=0;
	xse->get_texture_size(quad.texture, w, h);
	tex_width = (float)w;
	tex_height = (float)h;
	set_source_rect(Rect(0,0,tex_width, tex_height));
}
//=================================================================================================
Texture SpriteImpl::get_texture()
{
	return quad.texture;
}

}